home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / text / hyper / ADtoHT2_0.lha / Autodocs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  37.3 KB  |  1,368 lines

  1. #include <proto/exec.h>
  2.  
  3. /* SAS/C V5.10b is broken, so I can't use clib/alib_protos.h */
  4. void NewList(struct List *);
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10.  
  11. /************************************************************************/
  12.  
  13. #include "Includes.h"
  14. #include "Autodocs.h"
  15. #include "File.h"
  16. #include "FormatNode.h"
  17. #include "AdditionalDocs.h"
  18.  
  19. /************************************************************************/
  20.  
  21. static struct AutodocModuleNode *ExecModuleNode;
  22.  
  23. /************************************************************************/
  24.  
  25. struct AVLTree AutodocFileTree =
  26. {NULL, (int (*)(struct AVLNode *, struct AVLNode *)) nodecasecmp};
  27. struct AVLTree AutodocModuleTree =
  28. {NULL, (int (*)(struct AVLNode *, struct AVLNode *)) nodecmp};
  29. struct AVLTree AutodocNodeTree =
  30. {NULL, (int (*)(struct AVLNode *, struct AVLNode *)) nodecmp};
  31.  
  32. /************************************************************************/
  33. /*                                                                      */
  34. /* Create a new AutodocNodeNode                                         */
  35. /*                                                                      */
  36. /************************************************************************/
  37.  
  38. struct AutodocNodeNode *
  39. CreateAutodocNode (char *Name, struct AutodocModuleNode *AutodocModuleNode)
  40.  
  41. {
  42.   struct AutodocNode *AutodocNode;
  43.   struct AutodocNodeNode *AutodocNodeNode;
  44.   struct AutodocNodeNode **Current;
  45.  
  46.   if (!(AutodocNode = (struct AutodocNode *) SearchNode (&AutodocNodeTree, Name)))
  47.     {
  48.       AutodocNode = (struct AutodocNode *) CreateNode (Name, sizeof (*AutodocNode));
  49.       AutodocNode->Entries = NULL;
  50.       AutodocNode->Function = TRUE;
  51.       AVL_InsertNode (&AutodocNodeTree, &AutodocNode->AnyNode.AVLNode);
  52.     }
  53.   AutodocNodeNode = xmalloc (sizeof (*AutodocNodeNode));
  54.   AutodocNodeNode->AnyNode.Name = AutodocNode->AnyNode.Name;
  55.   AutodocNodeNode->AutodocModuleNode = AutodocModuleNode;
  56.   AutodocNodeNode->AutodocNode = AutodocNode;
  57.  
  58.   Current = &AutodocNode->Entries;
  59.   if (AutodocModuleNode != ExecModuleNode)
  60.     {
  61.       if (*Current && (*Current)->AutodocModuleNode == ExecModuleNode)
  62.     {
  63.       Current = &(*Current)->Next;
  64.     }
  65.       while (*Current &&
  66.          strcasecmp ((*Current)->AutodocModuleNode->AnyNode.Name,
  67.              AutodocNodeNode->AutodocModuleNode->AnyNode.Name) < 0)
  68.     {
  69.       Current = &(*Current)->Next;
  70.     }
  71.     }
  72.   AutodocNodeNode->Next = *Current;
  73.   *Current = AutodocNodeNode;
  74.  
  75.   return AutodocNodeNode;
  76. }
  77.  
  78. /************************************************************************/
  79. /*                                                                      */
  80. /* Find the "TABLE OF CONTENTS" line                                    */
  81. /*                                                                      */
  82. /************************************************************************/
  83.  
  84. static void
  85. FindTOC (void)
  86.  
  87. {
  88.   struct Word *Word;
  89.  
  90.   Word = ReadWord (TRUE);
  91.   if (!strcasecmp (Word->Word, "TABLE"))
  92.     {
  93.       FreeWord (Word);
  94.       Word = ReadWord (TRUE);
  95.       if (!Word->Newline && !strcasecmp (Word->Word, "OF"))
  96.     {
  97.       FreeWord (Word);
  98.       Word = ReadWord (TRUE);
  99.       if (!Word->Newline && !strcasecmp (Word->Word, "CONTENTS"))
  100.         {
  101.           FreeWord (Word);
  102.           return;
  103.         }
  104.     }
  105.     }
  106.   fprintf (stderr, "%s, line %lu: expected \x22TABLE OF CONTENTS\x22\n", ReadFilename, Word->Line);
  107.   CloseAll (RETURN_ERROR);
  108. }
  109.  
  110. /************************************************************************/
  111. /*                                                                      */
  112. /* Read and process a table of contents entry                           */
  113. /* FALSE if no entry was found                                          */
  114. /*                                                                      */
  115. /************************************************************************/
  116.  
  117. static int
  118. ReadTOCLine (struct AutodocFileNode *AutodocFileNode)
  119.  
  120. {
  121.   struct Word *Word;
  122.  
  123.   Word = ReadWord (FALSE);
  124.   if (strcmp ("\x0c", Word->Word))
  125.     {
  126.       char *Module;
  127.       int Information;
  128.       struct AutodocModuleNode *AutodocModuleNode;
  129.  
  130.       UnreadWord (Word);
  131.  
  132.       Module = ReadUntil ("/");
  133.       FreeWord (ReadWord (FALSE));    /* kill the terminator */
  134.  
  135.       /* get node name */
  136.       Information = FALSE;
  137.       Word = ReadWord (FALSE);
  138.       while (Word->Word[0] == '-')
  139.     {
  140.       Information = TRUE;
  141.       FreeWord (Word);
  142.       Word = ReadWord (FALSE);
  143.     }
  144.  
  145.       if (!(AutodocModuleNode = (struct AutodocModuleNode *) SearchNode (&AutodocModuleTree, Module)))
  146.     {
  147.       struct AutodocModuleNode **CurrentNode;
  148.  
  149.       AutodocModuleNode = xmalloc (sizeof (*AutodocModuleNode));
  150.       AutodocModuleNode->AnyNode.Name = Module;
  151.       AutodocModuleNode->AutodocFileNode = AutodocFileNode;
  152.       AutodocModuleNode->InfoNodes = NULL;
  153.       AutodocModuleNode->Nodes.Root = NULL;
  154.       AutodocModuleNode->Nodes.CompareNodes = AutodocNodeTree.CompareNodes;
  155.       for (CurrentNode = &AutodocFileNode->Modules; *CurrentNode; CurrentNode = &(*CurrentNode)->Next)
  156.         ;
  157.       *CurrentNode = AutodocModuleNode;
  158.       AutodocModuleNode->Next = NULL;
  159.       AVL_InsertNode (&AutodocModuleTree, (struct AVLNode *) AutodocModuleNode);
  160.       if (!strcmp (Module, "exec.library"))
  161.         {
  162.           ExecModuleNode = AutodocModuleNode;
  163.         }
  164.     }
  165.       else
  166.     {
  167.       free (Module);
  168.     }
  169.  
  170.       if (Information)
  171.     {
  172.       struct AutodocInfoNode *AutodocInfoNode;
  173.       struct AutodocInfoNode **CurrentNode;
  174.  
  175.       AutodocInfoNode = xmalloc (sizeof (*AutodocInfoNode));
  176.       AutodocInfoNode->Next = NULL;
  177.       AutodocInfoNode->Name = xstrdup (Word->Word);
  178.       AutodocInfoNode->Found = FALSE;
  179.       for (CurrentNode = &AutodocModuleNode->InfoNodes;
  180.            *CurrentNode;
  181.            CurrentNode = &(*CurrentNode)->Next)
  182.         ;
  183.       *CurrentNode = AutodocInfoNode;
  184.     }
  185.       else
  186.     {
  187.       struct AutodocNodeNode *AutodocNodeNode;
  188.  
  189.       AutodocNodeNode = CreateAutodocNode (Word->Word, AutodocModuleNode);
  190.       if (!strcmp (AutodocModuleNode->AnyNode.Name, "SAD"))
  191.         {
  192.           AutodocNodeNode->AutodocNode->Function = FALSE;
  193.         }
  194.       else
  195.         {
  196.           struct IncludeItemNode *IncludeItemNode;
  197.  
  198.           AutodocNodeNode->AutodocNode->Function =
  199.         (!(IncludeItemNode = (struct IncludeItemNode *)
  200.         SearchNode (&DefinesTree, AutodocNodeNode->AnyNode.Name)) ||
  201.          IncludeItemNode->Function);
  202.         }
  203.  
  204.       AutodocNodeNode->RealNode = AutodocNodeNode;
  205.       AutodocNodeNode->Found = FALSE;
  206.       if (AVL_InsertNode (&AutodocModuleNode->Nodes, &AutodocNodeNode->AnyNode.AVLNode))
  207.         {
  208.           fprintf (stderr, "%s, %lu: duplicate definition of \x22%s/%s\x22\n",
  209.                ReadFilename, Word->Line,
  210.                AutodocModuleNode->AnyNode.Name, AutodocNodeNode->AnyNode.Name);
  211.           CloseAll (RETURN_ERROR);
  212.         }
  213.     }
  214.       FreeWord (Word);
  215.       Word = ReadWord (FALSE);
  216.       while (!Word->Newline)
  217.     {
  218.       FreeWord (Word);
  219.       Word = ReadWord (FALSE);
  220.     }
  221.       UnreadWord (Word);
  222.       return TRUE;
  223.     }
  224.   FreeWord(Word);
  225.   return FALSE;
  226. }
  227.  
  228. /************************************************************************/
  229. /*                                                                      */
  230. /* Get the next label for TOC output                                    */
  231. /* Parameters: AutodocFileNode==NULL means AutodocModuleNode is valid   */
  232. /*                                                                      */
  233. /************************************************************************/
  234.  
  235. struct FormatParameters
  236. {
  237.   struct AutodocFileNode *AutodocFileNode;
  238.   struct AutodocModuleNode *AutodocModuleNode;
  239.  
  240.   struct AutodocNodeNode *AutodocNodeNode;
  241.   struct AVLStateInfo StateInfo;
  242. };
  243.  
  244. static char *
  245. AutodocNextLabel (char *PrevLabel, void *Parameters)
  246.  
  247. {
  248.   struct FormatParameters *Params;
  249.   char *Label;
  250.   char *t;
  251.  
  252.   Params = (struct FormatParameters *) Parameters;
  253.  
  254.   if (!PrevLabel)
  255.     {
  256.       if (Params->AutodocFileNode)
  257.     {
  258.       Params->AutodocModuleNode = Params->AutodocFileNode->Modules;
  259.     }
  260.       AVL_InitTraversal (&Params->AutodocModuleNode->Nodes, &Params->StateInfo);
  261.     }
  262.   else
  263.     {
  264.       if (!PrevLabel[0])
  265.     {
  266.       AVL_InitTraversal (&Params->AutodocModuleNode->Nodes, &Params->StateInfo);
  267.     }
  268.       free (PrevLabel);
  269.     }
  270.  
  271.   if (!(Params->AutodocNodeNode = (struct AutodocNodeNode *) AVL_InOrder (&Params->StateInfo)))
  272.     {
  273.       if (Params->AutodocFileNode)
  274.     {
  275.       if ((Params->AutodocModuleNode = Params->AutodocModuleNode->Next))
  276.         {
  277.           return xstrdup ("");
  278.         }
  279.     }
  280.       return NULL;
  281.     }
  282.  
  283.   Label = xmalloc (strlen (Params->AutodocNodeNode->AnyNode.Name) +
  284.            (Params->AutodocNodeNode->AutodocNode->Function ? 3 : 1));
  285.   t = stpcpy (Label, Params->AutodocNodeNode->AnyNode.Name);
  286.   if (Params->AutodocNodeNode->AutodocNode->Function)
  287.     strcpy (t, "()");
  288.   return Label;
  289. }
  290.  
  291. /************************************************************************/
  292. /*                                                                      */
  293. /* Output the link information for current label                        */
  294. /*                                                                      */
  295. /************************************************************************/
  296.  
  297. static void 
  298. AutodocPrintLink (void *Parameters)
  299.  
  300. {
  301.   WPrintf ("\x22%s%s",
  302.        ((struct FormatParameters *) Parameters)->AutodocNodeNode->RealNode->AnyNode.Name,
  303.        Arguments.Parentheses ? "()\x22" : "\x22");
  304. }
  305.  
  306. /************************************************************************/
  307. /*                                                                      */
  308. /* Output the table of contents                                         */
  309. /*                                                                      */
  310. /************************************************************************/
  311.  
  312. static void
  313. OutputTOC (struct AutodocFileNode *AutodocFileNode)
  314.  
  315. {
  316.   struct FormatParameters FormatParameters;
  317.   struct AutodocModuleNode *AutodocModuleNode;
  318.   int *ColWidth;
  319.  
  320.   WPrintf ("\n@NODE MAIN \x22%s\x22\n", AutodocFileNode->AnyNode.Name);
  321.   if (GlobalTOCFilename)
  322.     {
  323.       WPrintf("@TOC \x22%s/MAIN\x22\n",GlobalTOCFilename);
  324.     }
  325.  
  326.   FormatParameters.AutodocFileNode = AutodocFileNode;
  327.   ColWidth = FormatNode (AutodocNextLabel, &FormatParameters);
  328.  
  329.   FormatParameters.AutodocFileNode = NULL;
  330.   AutodocModuleNode = AutodocFileNode->Modules;
  331.   while (AutodocModuleNode)
  332.     {
  333.       struct AutodocInfoNode *AutodocInfoNode;
  334.  
  335.       WPrintf("\n");
  336.       WHeadline (AutodocModuleNode->AnyNode.Name);
  337.       WPrintf ("\n");
  338.  
  339.       for (AutodocInfoNode = AutodocModuleNode->InfoNodes;
  340.        AutodocInfoNode;
  341.        AutodocInfoNode = AutodocInfoNode->Next)
  342.     {
  343.       WPrintf ("@{\x22%s\x22 LINK \x22%s\x22}\n",
  344.            AutodocInfoNode->Name,
  345.            AutodocInfoNode->Name);
  346.     }
  347.       if (AutodocModuleNode->InfoNodes)
  348.     WPrintf ("\n");
  349.  
  350.       FormatParameters.AutodocModuleNode = AutodocModuleNode;
  351.       PrintNode (AutodocNextLabel, AutodocPrintLink, &FormatParameters, ColWidth);
  352.  
  353.       if ((AutodocModuleNode = AutodocModuleNode->Next))
  354.     WPrintf ("\n\n");
  355.     }
  356.   free (ColWidth);
  357.   WPrintf ("\n@ENDNODE\n");
  358. }
  359.  
  360. /************************************************************************/
  361. /*                                                                      */
  362. /* Check if the next stuff read is () (no newlines).                    */
  363. /* If yes, echo it. If no, do nothing.                                  */
  364. /* This function is used to get the '()' into a button (looks better).  */
  365. /*                                                                      */
  366. /************************************************************************/
  367.  
  368. static void 
  369. DoParentheses (void)
  370.  
  371. {
  372.   struct Word *Word;
  373.  
  374.   Word = ReadWord (TRUE);
  375.   if (Word->Word[0] == '(' && !Word->Newline)
  376.     {
  377.       struct Word *NextWord;
  378.  
  379.       NextWord = ReadWord (TRUE);
  380.       if (NextWord->Word[0] == ')' && !NextWord->Newline)
  381.     {
  382.       WriteWord (Word);
  383.       WriteWord (NextWord);
  384.       FreeWord (Word);
  385.       FreeWord (NextWord);
  386.       return;
  387.     }
  388.       UnreadWord (NextWord);
  389.     }
  390.   UnreadWord (Word);
  391. }
  392.  
  393. /************************************************************************/
  394. /*                                                                      */
  395. /* Check if the word references a module.                               */
  396. /* If yes, make a link and return TRUE. If no, do nothing and return    */
  397. /* FALSE.                                                               */
  398. /* Handles all cases, including module/functionname                     */
  399. /*                                                                      */
  400. /************************************************************************/
  401.  
  402. static int 
  403. DoModule (struct Word *Word, struct AutodocNodeNode *CurrentAutodocNode)
  404.  
  405. {
  406.   struct AutodocModuleNode *AutodocModuleNode;
  407.  
  408.   if (Word->Length > 5 && (AutodocModuleNode = (struct AutodocModuleNode *) SearchNode (&AutodocModuleTree, Word->Word)))
  409.     {
  410.       struct Word *NextWord;
  411.       struct Word *NodeName;    /* is only used when initialized */
  412.  
  413.       WriteWhitespace (Word);
  414.  
  415.       NextWord = ReadWord (TRUE);
  416.       if (NextWord->Word[0] == '/')
  417.     {
  418.       struct AutodocNodeNode *AutodocNodeNode;
  419.  
  420.       NodeName = ReadWord (TRUE);
  421.       if ((AutodocNodeNode = (struct AutodocNodeNode *) SearchNode (&AutodocModuleNode->Nodes, NodeName->Word)))
  422.         {
  423.           if (AutodocNodeNode->RealNode != CurrentAutodocNode)
  424.         {
  425.           if (NextWord->Newline || NodeName->Newline)
  426.             {
  427.               WriteWord (Word);
  428.               WriteWord (NextWord);
  429.               WriteWhitespace (NodeName);
  430.               WPrintf ("@{\x22");
  431.             }
  432.           else
  433.             {
  434.               WPrintf ("@{\x22");
  435.               WriteWord (Word);
  436.               WriteWord (NextWord);
  437.             }
  438.           WriteWord (NodeName);
  439.  
  440.           DoParentheses ();
  441.  
  442.           WPrintf ("\x22 LINK \x22");
  443.           if (!(CurrentAutodocNode &&
  444.             CurrentAutodocNode->AutodocModuleNode->AutodocFileNode == AutodocModuleNode->AutodocFileNode))
  445.             {
  446.               WPrintf ("%s/", AutodocModuleNode->AutodocFileNode->LinkName);
  447.             }
  448.           WPrintf ("%s%s\x22}",
  449.                AutodocNodeNode->RealNode->AnyNode.Name,
  450.                (Arguments.Parentheses && AutodocNodeNode->AutodocNode->Function) ? "()" : "");
  451.         }
  452.           else
  453.         {
  454.           WriteWord (Word);
  455.           WriteWord (NextWord);
  456.           WriteWord (NodeName);
  457.         }
  458.           FreeWord (NodeName);
  459.           FreeWord (NextWord);
  460.           return TRUE;
  461.         }
  462.     }
  463.       else
  464.     {
  465.       UnreadWord (NextWord);
  466.       NextWord = NULL;
  467.     }
  468.       if (!CurrentAutodocNode ||
  469.       CurrentAutodocNode->AutodocModuleNode != AutodocModuleNode)
  470.     {
  471.       WriteWhitespace (Word);
  472.       WPrintf ("@{\x22%s\x22 LINK \x22%s/MAIN\x22}",
  473.            Word->Word,
  474.            AutodocModuleNode->AutodocFileNode->LinkName);
  475.     }
  476.       else
  477.     {
  478.       WriteWord (Word);
  479.     }
  480.       if (NextWord)
  481.     {
  482.       WriteWord (NextWord);
  483.       WriteWord (NodeName);
  484.       FreeWord (NextWord);
  485.       FreeWord (NodeName);
  486.     }
  487.       return TRUE;
  488.     }
  489.   return FALSE;
  490. }
  491.  
  492. /************************************************************************/
  493. /*                                                                      */
  494. /* Check if the word references an header file.                         */
  495. /* If yes, make a link and return TRUE. If no, do nothing and return    */
  496. /* FALSE.                                                               */
  497. /*                                                                      */
  498. /************************************************************************/
  499.  
  500. static int 
  501. DoHeader (struct Word *Word, struct IncludeFileNode *CurrentIncludeFile)
  502.  
  503. {
  504.   if (Word->Length > 1)
  505.     {
  506.       struct MinList WordList;
  507.       char *Filename;
  508.  
  509.       NewList ((struct List *) &WordList);
  510.       AddTail ((struct List *) &WordList, (struct Node *) &Word->Node);
  511.       Filename = xstrdup (Word->Word);
  512.  
  513.       while (Word)
  514.     {
  515.       Word = ReadWord (TRUE);
  516.       AddTail ((struct List *) &WordList, (struct Node *) &Word->Node);
  517.       if (!Word->Whitespace && !Word->Newline && Word->Word[0] == '/')
  518.         {
  519.           Word = ReadWord (TRUE);
  520.           AddTail ((struct List *) &WordList, (struct Node *) &Word->Node);
  521.           if (!Word->Whitespace && !Word->Newline && Word->Length > 1)
  522.         {
  523.           char *NewFilename;
  524.           struct IncludeFileNode *IncludeFileNode;
  525.  
  526.           NewFilename = xmalloc (strlen (Filename) + 1 + Word->Length + 1);
  527.           stpcpy (stpcpy (stpcpy (NewFilename, Filename), "/"), Word->Word);
  528.           free (Filename);
  529.           Filename = NewFilename;
  530.  
  531.           if ((IncludeFileNode = (struct IncludeFileNode *) SearchNode (&IncludeFileTree, Filename)))
  532.             {
  533.               WriteWhitespace ((struct Word *) WordList.mlh_Head);
  534.               WPrintf ("@{\x22%s\x22 LINK \x22%s/File\x22}", Filename, IncludeFileNode->LinkName);
  535.               Word = (struct Word *) RemTail ((struct List *) &WordList);
  536.               while (!IsListEmpty ((struct List *) &WordList))
  537.             {
  538.               FreeWord (Word);
  539.               Word = (struct Word *) RemTail ((struct List *) &WordList);
  540.             }
  541.               free (Filename);
  542.               return TRUE;
  543.             }
  544.         }
  545.           else
  546.         {
  547.           Word = NULL;
  548.         }
  549.         }
  550.       else
  551.         {
  552.           Word = NULL;
  553.         }
  554.     }
  555.  
  556.       free (Filename);
  557.       Word = (struct Word *) RemTail ((struct List *) &WordList);
  558.       while (!IsListEmpty ((struct List *) &WordList))
  559.     {
  560.       UnreadWord (Word);
  561.       Word = (struct Word *) RemTail ((struct List *) &WordList);
  562.     }
  563.     }
  564.   return FALSE;
  565. }
  566.  
  567. /************************************************************************/
  568. /*                                                                      */
  569. /* Make a link to an autodoc entry.                                     */
  570. /*                                                                      */
  571. /************************************************************************/
  572.  
  573. static void 
  574. WriteAutodocLink (struct Word *Word,
  575.           struct AutodocNodeNode *AutodocNodeNode,
  576.           struct AutodocNodeNode *CurrentAutodocNode)
  577.  
  578. {
  579.   AutodocNodeNode = AutodocNodeNode->RealNode;
  580.  
  581.   WriteWhitespace (Word);
  582.   WPrintf ("@{\x22");
  583.   WriteWord (Word);
  584.   DoParentheses ();
  585.   WPrintf ("\x22 LINK \x22");
  586.   if (!CurrentAutodocNode ||
  587.       CurrentAutodocNode->AutodocModuleNode->AutodocFileNode != AutodocNodeNode->AutodocModuleNode->AutodocFileNode)
  588.     {
  589.       WPrintf ("%s/", AutodocNodeNode->AutodocModuleNode->AutodocFileNode->LinkName);
  590.     }
  591.   WPrintf ("%s%s\x22}",
  592.        AutodocNodeNode->RealNode->AnyNode.Name,
  593.        (Arguments.Parentheses && AutodocNodeNode->AutodocNode->Function) ? "()" : "");
  594. }
  595.  
  596. /************************************************************************/
  597. /*                                                                      */
  598. /* Check if the word references an autodoc node.                        */
  599. /* If yes, make a link and return TRUE. If no, do nothing and return    */
  600. /* FALSE.                                                               */
  601. /* This handles unqualified autodocs.                                   */
  602. /*                                                                      */
  603. /************************************************************************/
  604.  
  605. int 
  606. DoAutodoc (struct Word *Word, struct AutodocNodeNode *CurrentAutodocNode)
  607.  
  608. {
  609.   struct AutodocNode *AutodocNode;
  610.  
  611.   if ((AutodocNode = (struct AutodocNode *) SearchNode (&AutodocNodeTree, Word->Word)))
  612.     {
  613.       struct AutodocNodeNode *AutodocNodeNode;
  614.  
  615.       /* unambiguous link? */
  616.       if (!AutodocNode->Entries->Next)
  617.     {
  618.       if (AutodocNode->Entries->RealNode != CurrentAutodocNode)
  619.         {
  620.           WriteAutodocLink (Word, AutodocNode->Entries, CurrentAutodocNode);
  621.           return TRUE;
  622.         }
  623.       return FALSE;
  624.     }
  625.  
  626.       /* possible link into the same module? */
  627.       if (CurrentAutodocNode)
  628.     {
  629.       for (AutodocNodeNode = AutodocNode->Entries;
  630.            AutodocNodeNode;
  631.            AutodocNodeNode = AutodocNodeNode->Next)
  632.         {
  633.           if (AutodocNodeNode->AutodocModuleNode == CurrentAutodocNode->AutodocModuleNode)
  634.         {
  635.           if (AutodocNodeNode->RealNode != CurrentAutodocNode)
  636.             {
  637.               WriteAutodocLink (Word, AutodocNodeNode, CurrentAutodocNode);
  638.               return TRUE;
  639.             }
  640.           else
  641.             {
  642.               break;
  643.             }
  644.         }
  645.         }
  646.     }
  647.  
  648.       /* possible link into exec.library? */
  649.       if (AutodocNode->Entries->AutodocModuleNode == ExecModuleNode)
  650.     {
  651.       if (AutodocNode->Entries->RealNode != CurrentAutodocNode)
  652.         {
  653.           WriteAutodocLink (Word, AutodocNode->Entries, CurrentAutodocNode);
  654.           return TRUE;
  655.         }
  656.       return FALSE;
  657.     }
  658.  
  659.       /* if we are linking to the name we are currently working on      */
  660.       /* (i.e. CurrentAutodocNode IN AutodocNode->Entries), link to     */
  661.       /* the next entry in the list.                                    */
  662.       if (CurrentAutodocNode && CurrentAutodocNode->AutodocNode == AutodocNode)
  663.     {
  664.       if (CurrentAutodocNode->Next)
  665.         {
  666.           WriteAutodocLink (Word, CurrentAutodocNode->Next, CurrentAutodocNode);
  667.         }
  668.       else
  669.         {
  670.           WriteIdentifier (Word, NULL);
  671.         }
  672.       return TRUE;
  673.     }
  674.  
  675.       /* link to the first entry of the list */
  676.       WriteAutodocLink (Word, AutodocNode->Entries, CurrentAutodocNode);
  677.       return TRUE;
  678.     }
  679.   return FALSE;
  680. }
  681.  
  682. /************************************************************************/
  683. /*                                                                      */
  684. /* Look at the "current line" to see if it is really a headline        */
  685. /*                                                                      */
  686. /************************************************************************/
  687.  
  688. static int IsHeadline(void)
  689.  
  690. {
  691.   struct MinList WordList;
  692.   struct Word *Word;
  693.   int Headline;
  694.  
  695.   NewList((struct List *)&WordList);
  696.   Word=ReadWord(TRUE);
  697.  
  698.   if ((Headline=Word->Length && Word->Newline && Word->Whitespace<=4))
  699.     {
  700.       /* Another bug in the MUI autodocs... */
  701.       if (!strcmp(Word->Word,"SEE_ALSO"))
  702.     {
  703.       struct Word *NewWord;
  704.  
  705.       Word->Length=3;
  706.       Word->Word[3]='\0';
  707.  
  708.       NewWord=xmalloc(sizeof(*NewWord)+4);
  709.       NewWord->Line=Word->Line;
  710.       NewWord->Special=Word->Special;
  711.       NewWord->Length=4;
  712.       NewWord->Whitespace=1;
  713.       NewWord->Newline=0;
  714.       strcpy(NewWord->Word,"ALSO");
  715.  
  716.       UnreadWord(NewWord);
  717.     }
  718.  
  719.       do
  720.     {
  721.       size_t i;
  722.  
  723.       for (i=0; i<Word->Length && (Headline=isupper(Word->Word[i])); i++)
  724.         ;
  725.       AddTail((struct List *)&WordList,(struct Node *)&Word->Node);
  726.       Word=ReadWord(TRUE);
  727.     }
  728.       while (Headline && Word->Length && !Word->Newline);
  729.     }
  730.   do
  731.     {
  732.       UnreadWord(Word);
  733.     }
  734.   while ((Word=(struct Word *)RemTail((struct List *)&WordList)));
  735.   return Headline;
  736. }
  737.  
  738. /************************************************************************/
  739. /*                                                                      */
  740. /* Check if the current line should be appended to the previous line.    */
  741. /*                                                                      */
  742. /************************************************************************/
  743.  
  744. static int AppendLine(void)
  745.  
  746. {
  747.   struct MinList WordList;
  748.   struct Word *Word;
  749.   size_t LineLength;
  750.   int RC;
  751.  
  752.   NewList((struct List *)&WordList);
  753.   LineLength=0;
  754.   RC=FALSE;
  755.   Word=ReadWord(TRUE);
  756.   do
  757.     {
  758.       LineLength+=Word->Whitespace+Word->Length;
  759.       AddTail((struct List *)&WordList,(struct Node *)&Word->Node);
  760.       Word=ReadWord(TRUE);
  761.     }
  762.   while (!Word->Newline && Word->Length);
  763.   UnreadWord(Word);
  764.   if (Word->Whitespace>4 || IsHeadline())
  765.     {
  766.       if (LineLength<4)
  767.     {
  768.       ((struct Word *)WordList.mlh_Head)->Whitespace=1;
  769.       ((struct Word *)WordList.mlh_Head)->Newline=0;
  770.       RC=TRUE;
  771.     }
  772.     }
  773.   while ((Word=(struct Word *)RemTail((struct List *)&WordList)))
  774.     {
  775.       UnreadWord(Word);
  776.     }
  777.   return RC;
  778. }
  779.  
  780. /************************************************************************/
  781. /*                                                                      */
  782. /* Indent all lines until the next "headline" is found.            */
  783. /*                                                                      */
  784. /************************************************************************/
  785.  
  786. static void ReindentParagraph(void)
  787.  
  788. {
  789.   struct MinList WordList;
  790.   struct Word *Word;
  791.   int MinSpaces;
  792.  
  793.   NewList((struct List *)&WordList);
  794.  
  795.   /* step 1: determine the minimum indention of the paragraph ("how far left is the leftmost line?") */
  796.   MinSpaces=8;
  797.   while (!IsHeadline())
  798.     {
  799.       Word=ReadWord(TRUE);
  800.       if (Word->Newline && Word->Length && Word->Word[0]!=0x0c && Word->Whitespace<MinSpaces)
  801.     {
  802.       MinSpaces=Word->Whitespace;
  803.     }
  804.       do
  805.     {
  806.       AddTail((struct List *)&WordList,(struct Node *)&Word->Node);
  807.       Word=ReadWord(TRUE);
  808.     }
  809.       while (!Word->Newline && Word->Length);
  810.       UnreadWord(Word);
  811.     }
  812.  
  813.   /* now, indent the whole thing by 8-MinSpaces spaces. */
  814.   while ((Word=(struct Word *)RemTail((struct List *)&WordList)))
  815.     {
  816.       if (Word->Newline)
  817.     {
  818.       Word->Whitespace+=(8-MinSpaces);
  819.     }
  820.       UnreadWord(Word);
  821.     }
  822. }
  823.  
  824. /************************************************************************/
  825. /*                                                                      */
  826. /* Convert the node text                                                */
  827. /* If Comment==TRUE, then this is really a comment in in an include     */
  828. /* file. This implies a slightly different handling.                    */
  829. /* Node is either an AutodocNodeNode or an IncludeFileNode              */
  830. /*                                                                      */
  831. /************************************************************************/
  832.  
  833. void
  834. ConvertNodeText (int Comment, void *Node)
  835.  
  836. {
  837.   enum
  838.   {
  839.     GENERIC = 0, SEE_ALSO = 1
  840.   }
  841.   Paragraph;
  842.  
  843.   Paragraph = GENERIC;
  844.   while (TRUE)
  845.     {
  846.       struct Word *Word;
  847.  
  848.       Word = ReadWord (TRUE);
  849.       if (Word->Length)
  850.     {
  851.       /* check for end of text */
  852.       if (Comment)
  853.         {
  854.           if (Word->Word[0] == '*')
  855.         {
  856.           struct Word *NextWord;
  857.  
  858.           NextWord = ReadWord (TRUE);
  859.           if (!NextWord->Newline && !NextWord->Whitespace && NextWord->Word[0] == '/')
  860.             {
  861.               WriteWord (Word);
  862.               WriteWord (NextWord);
  863.               FreeWord (Word);
  864.               FreeWord (NextWord);
  865.  
  866.               /* now, check whether the next thing is another comment. */
  867.               /* We treat this as one comment. */
  868.               Word = ReadWord (TRUE);
  869.               if (Word->Word[0] == '/')
  870.             {
  871.               NextWord = ReadWord (TRUE);
  872.               if (!NextWord->Newline && !NextWord->Whitespace && NextWord->Word[0] == '*')
  873.                 {
  874.                   WriteWord (Word);
  875.                   WriteWord (NextWord);
  876.                   FreeWord (Word);
  877.                   FreeWord (NextWord);
  878.                   continue;
  879.                 }
  880.               UnreadWord (NextWord);
  881.             }
  882.               UnreadWord (Word);
  883.               break;
  884.             }
  885.           else
  886.             {
  887.               UnreadWord (NextWord);
  888.             }
  889.         }
  890.         }
  891.       else
  892.         {
  893.           if (Word->Word[0] == '\x0c')
  894.         {
  895.           FreeWord (Word);
  896.           break;
  897.         }
  898.         }
  899.  
  900.       if (!Comment && Word->Newline && Word->Whitespace <= 4 && Node &&
  901.           strcmp(((struct AutodocNodeNode *)Node)->AutodocModuleNode->AnyNode.Name,"SAD"))
  902.         {
  903.           UnreadWord(Word);
  904.           if (IsHeadline())
  905.         {
  906.           Word=ReadWord(TRUE);
  907.           if (!strcasecmp (Word->Word, "SEE"))
  908.             {
  909.               Paragraph = SEE_ALSO;
  910.             }
  911.           else
  912.             {
  913.               Paragraph = GENERIC;
  914.             }
  915.           if (*Arguments.Version >= 39)
  916.             {
  917.               WPrintf ("@{b}");
  918.             }
  919.           do
  920.             {
  921.               WriteWord(Word);
  922.               FreeWord(Word);
  923.               Word=ReadWord(TRUE);
  924.             }
  925.           while (Word->Length && !Word->Newline);
  926.           UnreadWord(Word);
  927.           if (*Arguments.Version >= 39)
  928.             {
  929.               WPrintf ("@{ub}");
  930.             }
  931.         }
  932.           else
  933.         {
  934.           if (!AppendLine())
  935.             {
  936.               ReindentParagraph();
  937.             }
  938.         }
  939.         }
  940.       else if (!strcmp (Word->Word, "struct") ||
  941.            !strcmp (Word->Word, "union"))
  942.         {
  943.           struct Word *StructUnionTag;
  944.           struct IncludeItemNode *IncludeItemNode;
  945.  
  946.           StructUnionTag = ReadWord (FALSE);
  947.           if ((IncludeItemNode = (struct IncludeItemNode *)
  948.           SearchNode (Word->Word[0] == 'u' ? &UnionTree : &StructureTree, StructUnionTag->Word)))
  949.         {
  950.           WriteWhitespace (Word);
  951.           if (!StructUnionTag->Newline)
  952.             {
  953.               WPrintf ("@{\x22");
  954.               WriteWord (Word);
  955.             }
  956.           else
  957.             {
  958.               WriteWord (Word);
  959.               WriteWhitespace (StructUnionTag);
  960.               WPrintf ("@{\x22");
  961.             }
  962.           WriteWord (StructUnionTag);
  963.           WPrintf ("\x22 LINK \x22%s/File\x22 %lu}",
  964.             IncludeItemNode->Entries->IncludeFileNode->LinkName,
  965.                IncludeItemNode->Entries->Line);
  966.         }
  967.           else
  968.         {
  969.           WriteWord (Word);
  970.           WriteWord (StructUnionTag);
  971.         }
  972.           FreeWord (Word);
  973.           FreeWord (StructUnionTag);
  974.         }
  975.  
  976.       else if (Word->Length > 2)
  977.         {
  978.           if (!Word->Special && Paragraph != SEE_ALSO)
  979.         {
  980.           struct Word *NextWord;
  981.  
  982.           NextWord = ReadWord (TRUE);
  983.           UnreadWord (NextWord);
  984.           if (NextWord->Word[0] == '(')
  985.             {
  986.               if (!DoAutodoc (Word, Comment ? NULL : Node))
  987.             {
  988.               WriteWord (Word);
  989.             }
  990.               FreeWord (Word);
  991.               continue;
  992.             }
  993.           if (DoHeader (Word, Comment ? Node : NULL))
  994.             {
  995.               FreeWord (Word);
  996.               continue;
  997.             }
  998.         }
  999.           else
  1000.         /* Word->Special == TRUE or SEE_ALSO */
  1001.         {
  1002.           if (!DoAutodoc (Word, Comment ? NULL : Node) &&
  1003.               !DoModule (Word, Comment ? NULL : Node) &&
  1004.               !DoHeader (Word, Comment ? Node : NULL))
  1005.             {
  1006.               WriteIdentifier (Word, Comment ? Node : NULL);
  1007.             }
  1008.           FreeWord (Word);
  1009.           continue;
  1010.         }
  1011.           WriteWord (Word);
  1012.           FreeWord (Word);
  1013.         }
  1014.  
  1015.       else
  1016.         {
  1017.           /* echo it normally */
  1018.           if (!DoModule (Word, Comment ? NULL : Node) &&
  1019.           !DoHeader (Word, Comment ? Node : NULL))
  1020.         {
  1021.           WriteWord (Word);
  1022.         }
  1023.           FreeWord (Word);
  1024.         }
  1025.     }
  1026.       else
  1027.     {
  1028.       /* end of file reached */
  1029.       FreeWord(Word);
  1030.       break;
  1031.     }
  1032.     }
  1033. }
  1034.  
  1035. /************************************************************************/
  1036. /*                                                                      */
  1037. /* Convert an autodoc node                                              */
  1038. /* Return FALSE for no more nodes                                       */
  1039. /*                                                                      */
  1040. /************************************************************************/
  1041.  
  1042. static int
  1043. ConvertNode (struct AutodocFileNode *AutodocFileNode)
  1044.  
  1045. {
  1046.   struct AutodocModuleNode *AutodocModuleNode;
  1047.   struct AutodocNodeNode *AutodocNodeNode;
  1048.   int Information;
  1049.   struct Word *Module;
  1050.   struct Word *Word;
  1051.   struct Word *NodeName;
  1052.  
  1053.   /* get module name ("exec.library") */
  1054.   Module = ReadWord (TRUE);
  1055.   if (!Module->Length)
  1056.     {
  1057.       FreeWord(Module);
  1058.       return FALSE;
  1059.     }
  1060.  
  1061.   Word=ReadWord (FALSE);
  1062.   if (Word->Word[0]!='/')
  1063.     {
  1064.       fprintf(stderr,"%s, line %lu: expected '/'.\n",ReadFilename,Word->Line);
  1065.       CloseAll(RETURN_ERROR);
  1066.     }
  1067.   FreeWord(Word);
  1068.  
  1069.   if (!(AutodocModuleNode = (struct AutodocModuleNode *) SearchNode (&AutodocModuleTree, Module->Word)))
  1070.     {
  1071.       fprintf (stderr, "%s, line %lu: module \x22%s\x22 not found in table of contents\n",
  1072.            ReadFilename, Module->Line, Module->Word);
  1073.       CloseAll (RETURN_ERROR);
  1074.     }
  1075.   FreeWord(Module);
  1076.  
  1077.   NodeName = ReadWord (FALSE);
  1078.   Word=ReadWord(FALSE);
  1079.   while (!Word->Newline && Word->Word[0] != '/')
  1080.     {
  1081.       FreeWord (Word);
  1082.       Word = ReadWord (FALSE);
  1083.     }
  1084.   if (Word->Newline)
  1085.     {
  1086.       UnreadWord(Word);
  1087.       Word = NodeName;
  1088.     }
  1089.   else
  1090.     {
  1091.       FreeWord (Word);
  1092.       FreeWord (NodeName);
  1093.       Word=ReadWord(FALSE);
  1094.     }
  1095.  
  1096.   Information = FALSE;
  1097.   while (Word->Word[0] == '-')
  1098.     {
  1099.       Information = TRUE;
  1100.       FreeWord (Word);
  1101.       Word = ReadWord (FALSE);
  1102.     }
  1103.  
  1104.   if (Information)
  1105.     {
  1106.       struct AutodocInfoNode *AutodocInfoNode;
  1107.  
  1108.       for (AutodocInfoNode = AutodocModuleNode->InfoNodes;
  1109.        AutodocInfoNode && strcmp (AutodocInfoNode->Name, Word->Word);
  1110.        AutodocInfoNode = AutodocInfoNode->Next)
  1111.     ;
  1112.       if (!AutodocInfoNode)
  1113.     {
  1114.       int RC;
  1115.  
  1116.       fprintf (stderr, "%s, line %lu: info-node \x22%s/%s\x22 not found in table of contents\n",
  1117.            ReadFilename, Word->Line, AutodocModuleNode->AnyNode.Name, Word->Word);
  1118.       SetRC (RETURN_WARN);
  1119.       while (Word->Length && Word->Word[0] != 0x0c)
  1120.         {
  1121.           FreeWord (Word);
  1122.           Word = ReadWord (TRUE);
  1123.         }
  1124.       RC = Word->Length;
  1125.       FreeWord (Word);
  1126.       return RC;
  1127.     }
  1128.       AutodocInfoNode->Found = TRUE;
  1129.       AutodocNodeNode = NULL;
  1130.       WPrintf ("@NODE \x22%s\x22 \x22%s/%s (information)\x22\n",
  1131.            AutodocInfoNode->Name,
  1132.            AutodocModuleNode->AnyNode.Name,
  1133.            AutodocInfoNode->Name);
  1134.     }
  1135.   else
  1136.     {
  1137.     /* !Information */
  1138.     NarratorBugFixed:
  1139.       if (!(AutodocNodeNode = (struct AutodocNodeNode *) SearchNode (&AutodocModuleNode->Nodes, Word->Word)))
  1140.     {
  1141.       int RC;
  1142.  
  1143.       /* hack: check for the famous narrator.doc bug */
  1144.       if (!strcasecmp (AutodocModuleNode->AnyNode.Name, "narrator.device") &&
  1145.           !strcmp (Word->Word, "CMD_Read"))
  1146.         {
  1147.           if (Pass2)
  1148.         {
  1149.           fprintf (stderr, "%s",
  1150.                "Hey! I just encountered the narrator.doc (CMD_Read) bug! It's still there!\n"
  1151.                "But I'm a very smart program, so of course I know how to deal with it.\n");
  1152.         }
  1153.           strcpy (Word->Word, "CMD_READ");
  1154.           goto NarratorBugFixed;
  1155.         }
  1156.       fprintf (stderr, "%s, line %lu: \x22%s/%s\x22 not found in table of contents\n",
  1157.            ReadFilename, Word->Line, AutodocModuleNode->AnyNode.Name, Word->Word);
  1158.       SetRC (RETURN_WARN);
  1159.       while (Word->Length && Word->Word[0] != 0x0c)
  1160.         {
  1161.           FreeWord (Word);
  1162.           Word = ReadWord (TRUE);
  1163.         }
  1164.       RC = Word->Length;
  1165.       FreeWord (Word);
  1166.       return RC;
  1167.     }
  1168.       AutodocNodeNode->Found = TRUE;
  1169.       WPrintf ("@NODE \x22%s%s\x22 \x22%s/%s%s\x22\n",
  1170.            AutodocNodeNode->AnyNode.Name,
  1171.            (AutodocNodeNode->AutodocNode->Function && Arguments.Parentheses) ? "()" : "",
  1172.            AutodocModuleNode->AnyNode.Name,
  1173.            AutodocNodeNode->AnyNode.Name,
  1174.            AutodocNodeNode->AutodocNode->Function ? "()" : "");
  1175.     }
  1176.  
  1177.   FreeWord (Word);
  1178.   Word = ReadWord (FALSE);
  1179.   while (!Word->Newline)
  1180.     {
  1181.       FreeWord (Word);
  1182.       Word = ReadWord (FALSE);
  1183.     }
  1184.   UnreadWord (Word);
  1185.  
  1186.   if (Pass2)
  1187.     {
  1188.       ConvertNodeText (FALSE, AutodocNodeNode);
  1189.       WPrintf ("\n\n@ENDNODE\n");
  1190.  
  1191.       return TRUE;
  1192.     }
  1193.   else
  1194.     {
  1195.       int SynopsisDone;
  1196.       int NodeCount;
  1197.       struct AVLStateInfo StateInfo;
  1198.  
  1199.       AVL_InitTraversal(&AutodocModuleNode->Nodes,&StateInfo);
  1200.       for (NodeCount=0; NodeCount<2 && AVL_InOrder(&StateInfo); NodeCount++)
  1201.     ;
  1202.  
  1203.       SynopsisDone = (NodeCount<2) || (AutodocNodeNode && !AutodocNodeNode->AutodocNode->Function);
  1204.       while (TRUE)
  1205.     {
  1206.       Word = ReadWord (TRUE);
  1207.       if (!Word->Length)
  1208.         {
  1209.           FreeWord (Word);
  1210.           return FALSE;
  1211.         }
  1212.       if (Word->Word[0] == 0x0c)
  1213.         {
  1214.           FreeWord (Word);
  1215.           return TRUE;
  1216.         }
  1217.       if (SynopsisDone)
  1218.         {
  1219.           FreeWord (Word);
  1220.           return ReadSkip () == 0x0c;
  1221.         }
  1222.       if (Word->Newline && Word->Whitespace < 5 && !strcmp ("SYNOPSIS", Word->Word))
  1223.         {
  1224.           while (TRUE)
  1225.         {
  1226.           FreeWord (Word);
  1227.           Word = ReadWord (TRUE);
  1228.           if (!Word->Length || Word->Word[0] == 0x0c)
  1229.             {
  1230.               break;
  1231.             }
  1232.           if (Word->Newline && Word->Whitespace < 5)
  1233.             {
  1234.               break;
  1235.             }
  1236.           if (Word->Length > 2)
  1237.             {
  1238.               struct Word *NextWord;
  1239.               
  1240.               NextWord = ReadWord (TRUE);
  1241.               if (NextWord->Word[0] == '(')
  1242.             {
  1243.               int NestCount;
  1244.               
  1245.               NestCount = 1;
  1246.               while (NestCount)
  1247.                 {
  1248.                   FreeWord (NextWord);
  1249.                   NextWord = ReadWord (FALSE);
  1250.                   if (NextWord->Word[0] == '(')
  1251.                 NestCount++;
  1252.                   else if (NextWord->Word[0] == ')')
  1253.                 NestCount--;
  1254.                 }
  1255.               FreeWord (NextWord);
  1256.               if (strcmp (Word->Word, AutodocNodeNode->AnyNode.Name) &&
  1257.                   !SearchNode (&AutodocModuleNode->Nodes, Word->Word))
  1258.                 {
  1259.                   struct AutodocNodeNode *VarAutodocNodeNode;
  1260.                   
  1261.                   VarAutodocNodeNode = CreateAutodocNode (Word->Word, AutodocModuleNode);
  1262.                   
  1263.                   VarAutodocNodeNode->RealNode = AutodocNodeNode;
  1264.                   VarAutodocNodeNode->Found = TRUE;
  1265.                   
  1266.                   AVL_InsertNode (&AutodocModuleNode->Nodes,
  1267.                           &VarAutodocNodeNode->AnyNode.AVLNode);
  1268.                 }
  1269.             }
  1270.               else
  1271.             {
  1272.               UnreadWord (NextWord);
  1273.             }
  1274.             }
  1275.         }
  1276.           UnreadWord (Word);
  1277.           SynopsisDone = TRUE;
  1278.         }
  1279.       else
  1280.         {
  1281.           FreeWord (Word);
  1282.         }
  1283.     }
  1284.     }
  1285.   /* not reached */
  1286. }
  1287.  
  1288. /************************************************************************/
  1289. /*                                                                      */
  1290. /* Skip the table of contents                                           */
  1291. /*                                                                      */
  1292. /************************************************************************/
  1293.  
  1294. static void
  1295. SkipTOC (void)
  1296.  
  1297. {
  1298.   struct Word *Word;
  1299.   int Done;
  1300.  
  1301.   do
  1302.     {
  1303.       Word=ReadWord(FALSE);
  1304.       Done=(Word->Word[0]==0x0c);
  1305.       FreeWord(Word);
  1306.     }
  1307.   while (!Done);
  1308. }
  1309.  
  1310. /************************************************************************/
  1311. /*                                                                      */
  1312. /* Process a single autodoc file, first pass                            */
  1313. /*                                                                      */
  1314. /************************************************************************/
  1315.  
  1316. void
  1317. ProcessAutodocFile1 (char *Filename)
  1318.  
  1319. {
  1320.   struct AutodocFileNode *AutodocFileNode;
  1321.  
  1322.   ROpen (AUTODOCDIR, Filename);
  1323.   WOpen (HYPERAUTODOCDIR, Filename);
  1324.  
  1325.   AutodocFileNode = (struct AutodocFileNode *) CreateNode (Filename, sizeof (*AutodocFileNode));
  1326.   AutodocFileNode->LinkName = xstrdup (Arguments.FullPath ? WriteFilename : Filename);
  1327.   AutodocFileNode->LinkName[strlen (AutodocFileNode->LinkName) - 4] = '\0';
  1328.   AutodocFileNode->Modules = NULL;
  1329.   AVL_InsertNode (&AutodocFileTree, &AutodocFileNode->AnyNode.AVLNode);
  1330.  
  1331.   FindTOC ();
  1332.   while (ReadTOCLine (AutodocFileNode))
  1333.     ;
  1334.  
  1335.   while (ConvertNode (AutodocFileNode))
  1336.     ;
  1337.  
  1338.   WClose ();
  1339.   RClose ();
  1340. }
  1341.  
  1342. /************************************************************************/
  1343. /*                                                                      */
  1344. /* Process a single autodoc file, second pass                           */
  1345. /*                                                                      */
  1346. /************************************************************************/
  1347.  
  1348. void
  1349. ProcessAutodocFile2 (struct AutodocFileNode *AutodocFileNode)
  1350.  
  1351. {
  1352.   printf ("Converting %s\n", AutodocFileNode->AnyNode.Name);
  1353.  
  1354.   ROpen (AUTODOCDIR, AutodocFileNode->AnyNode.Name);
  1355.   WOpen (HYPERAUTODOCDIR, AutodocFileNode->LinkName);
  1356.  
  1357.   WriteHeader (AutodocFileNode->LinkName, ReadFilename);
  1358.  
  1359.   OutputTOC (AutodocFileNode);
  1360.   SkipTOC ();
  1361.  
  1362.   while (ConvertNode (AutodocFileNode))
  1363.     ;
  1364.  
  1365.   RClose ();
  1366.   WClose ();
  1367. }
  1368.